#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <map>
#include <algorithm>
#include <time.h>
#include <net/if.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>

#include "externalMsgApi4XA.h"
#include "../../fep/cli_main.h"
#include "../../fep/xml_conf.h"
#include "../../fep/wrapperjson.h"
#include "../../fep/cmd.h"
#include "../../fep/buf_misc.h"

using namespace std;
static I32 setCellNum = 0;
extern char ssh_state;

//message builder
static void buildBsTimeRequest(char* output, int* outlen);
static void buildBsGeneralResponse(I32 code, I32 result, I8 *indata, I8 *outdata, I32* len);
static void buildBsDeviceRegisterRequest(RegisterMsg *reginfo, I8 *outdata, I32* len);
static void buildBsRespnoseWithId(I32 code, I32 result, I8 *indata, I8 *outdata, I32* len);
static void buildBsFtpInfo(I32 code, I8 *indata, I8 *outdata, I32* len);
static void buildBsSnifferResult(I32 code, I8 *indata, I8 *outdata, I32* len);
static void buildBsAlarmUeReport(I32 code, I32 result, I8 *indata, I8 *outdata, I32* len);
static void buildBsRfConfiguration(I32 code, I32 result, I8 *indata, I8 *outdata, I32* len);
static void buildBsDeviceStatusReport(DevStaus *status, char* output, int* outlen);
static void buildBsQueryAlarmUeResponse(I32 code, I32 result, I8 *indata, I8 *outdata, I32* len);

//message handler
static void handleBsConfigRequest(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsTxTurnOnRequest(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsTxTurnOffRequest(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsRfConfigRequest(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsRebootRequest(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsQueryConfigRequest(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsTimeConfigRequest(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsAlarmUeRequest(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsFtpConfigRequest(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsFtpQueryRequest(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsUpgradeRequest(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsQueryLog(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsDeviceRegisterResponse(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsSnifferRequest(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsSnifferConfigRequest(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsHeartBeatReponse(const char* data, ssize_t len, char* input, int *inLen);
static bool ResolveXinanapiMessageHandler(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsRemoteSshOn(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsRemoteSshOff(const char* data, ssize_t len, char* input, int *inLen);
static void handleBsVersionSshState(const char* data, ssize_t len, char* input, int *inLen);
static void buildBsVersionSshState(I32 code, I32 result, I8 *indata, I8 *outdata, I32* len);

//message handler callback
HANDLER handlers[]=
{
    {XINAN_MESSAGE_CODE_BS_CONFIG_REQUEST, handleBsConfigRequest},
    {XINAN_MESSAGE_CODE_TX_TURNON_REQUEST, handleBsTxTurnOnRequest},
    {XINAN_MESSAGE_CODE_TX_TURNOFF_REQUEST, handleBsTxTurnOffRequest},
    {XINAN_MESSAGE_CODE_RF_CONFIG_REQUEST, handleBsRfConfigRequest},
    {XINAN_MESSAGE_CODE_BS_REBOOT_REQUEST, handleBsRebootRequest},
    {XINAN_MESSAGE_CODE_QUERY_CONFIG_REQUEST, handleBsQueryConfigRequest},
    {XINAN_MESSAGE_CODE_ALARMUE_CONFIG_REQUEST, handleBsAlarmUeRequest},
    {XINAN_MESSAGE_CODE_TIME_CONFIG_REQUEST, handleBsTimeConfigRequest},
    {XINAN_MESSAGE_CODE_FTP_CONFIG_REQUEST, handleBsFtpConfigRequest},
    {XINAN_MESSAGE_CODE_FTP_QUERY_REQUEST, handleBsFtpQueryRequest},
    {XINAN_MESSAGE_CODE_UPGRADE_REQUEST, handleBsUpgradeRequest},
    {XINAN_MESSAGE_CODE_QUERY_LOG, handleBsQueryLog},
    {XINAN_MESSAGE_CODE_DEVICE_REGISTER_RESPONSE, handleBsDeviceRegisterResponse},
    {XINAN_MESSAGE_CODE_DEVICE_SNIFFER_CONFIG_REQUEST, handleBsSnifferConfigRequest},
    {XINAN_MESSAGE_CODE_STATUS_RESPONSE, handleBsHeartBeatReponse},
    {XINAN_MESSAGE_CODE_SSH_ON_REQUEST, handleBsRemoteSshOn},
    {XINAN_MESSAGE_CODE_SSH_OFF_REQUEST, handleBsRemoteSshOff},
    {XINAN_MESSAGE_CODE_VERSION_SSH_QUERY, handleBsVersionSshState}
};

static const value_string cmdResponse[] = {
{CFG_UPDATA_TAC_CYCLE, XINAN_MESSAGE_CODE_BS_CONFIG_RESPONSE},
{CFG_DET_INTVL, XINAN_MESSAGE_CODE_BS_CONFIG_RESPONSE},
{CT_WIRELISS_ON, XINAN_MESSAGE_CODE_TX_TURNON_RESPONSE},
{CT_BBU_PW_ON, XINAN_MESSAGE_CODE_TX_TURNON_RESPONSE},
{CT_WIRELISS_OFF, XINAN_MESSAGE_CODE_TX_TURNOFF_RESPONSE},
{CT_BBU_PW_OFF, XINAN_MESSAGE_CODE_TX_TURNOFF_RESPONSE},
{CFG_WIRELESS,XINAN_MESSAGE_CODE_RF_CONFIG_RESPONSE},
{CT_RESRART, XINAN_MESSAGE_CODE_BS_REBOOT_RESPONSE},
{CT_TIME_SYNC, XINAN_MESSAGE_CODE_TIME_CONFIG_RESPONSE},
{SR_TOTAL_CFG, XINAN_MESSAGE_CODE_QUERY_CONFIG_RESPONSE},
{CFG_FTP_INFO, XINAN_MESSAGE_CODE_FTP_CONFIG_RESPONSE},
{SR_FTP_INFO, XINAN_MESSAGE_CODE_FTP_QUERY_RESPONSE},
{CT_SNIFFER, XINAN_MESSAGE_CODE_DEVICE_SNIFFER_RESPONSE},
{CFG_AIR_SNIFFER, XINAN_MESSAGE_CODE_DEVICE_SNIFFER_CONFIG_RESPONSE},
{CFG_WIRELESS, XINAN_MESSAGE_CODE_RF_CONFIG_RESPONSE},
{CFG_BLACKLIST_ADD,  XINAN_MESSAGE_CODE_ALARMUE_CONFIG_RESPONSE},
{CFG_BLACKLIST_DEL,  XINAN_MESSAGE_CODE_ALARMUE_CONFIG_RESPONSE},
{SR_BLACKLIST, XINAN_MESSAGE_CODE_ALARMUE_CONFIG_RESPONSE},
{CT_REMOTE_SSH_ON, XINAN_MESSAGE_CODE_SSH_ON_RESPONSE},
{CT_REMOTE_SSH_OFF, XINAN_MESSAGE_CODE_SSH_OFF_RESPONSE},
{SR_DEV_VERSION, XINAN_MESSAGE_CODE_VERSION_SSH_RESPONSE},
{0xFFFF, NULL}
};

xinAnServerState_t xinAnServerState = XINAN_SERVER_IDLE;
static std::string recvSmtpMsgBuf;
static U32  currentSmtpMsgSize = 0;

static char* queryWanIpAddress()
{
    int sockfd = -1, sockfd1 = -1;
    struct sockaddr_in *addr;
    struct ifreq tmp, tmp1;
    char *addrPtr;
    strcpy(tmp.ifr_name, "3g-wan");

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        cli_app_log(CLI_LOG_NOTICE, "open socket failed\n");		
        return NULL;
    }
    if ((ioctl(sockfd, SIOCGIFADDR, &tmp)) < 0)
    {
        close(sockfd);
        cli_app_log(CLI_LOG_NOTICE, "open socket 3gwan failed\n");
        strcpy(tmp1.ifr_name, "eth1");
        sockfd1 = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd1 < 0)
        {
            cli_app_log(CLI_LOG_NOTICE, "open socket eth1 failed \n");
            return NULL;
        }
        if ((ioctl(sockfd1, SIOCGIFADDR, &tmp1)) < 0)
        {
            cli_app_log(CLI_LOG_NOTICE, "open socket eth1 failed\n");
        }
        else
        {
            addr = (struct sockaddr_in *)&(tmp1.ifr_addr);
            addrPtr = (char *)inet_ntoa(addr->sin_addr);
            memcpy(addrPtr + strlen(addrPtr), "\0", 1);
            close(sockfd1); 
            cli_app_log(CLI_LOG_NOTICE, "wan ip %s\n", addrPtr);
            return addrPtr;
        }
        return "10.235.132.221";
    }
    else
    {
        addr = (struct sockaddr_in *)&(tmp.ifr_addr);
        addrPtr = (char *)inet_ntoa(addr->sin_addr);
        memcpy(addrPtr + strlen(addrPtr), "\0", 1);
        close(sockfd); 
        cli_app_log(CLI_LOG_NOTICE, "wan ip %s\n", addrPtr);
        return addrPtr;
    }
}

const char* matchStringValue(const value_string *vs, const I32 val)
{
    U32 i = 0;
  
    if(vs) 
    {
        while (vs[i].strptr) 
        {
            if (vs[i].value == val) 
            {
               return(vs[i].strptr);
            }

            i++;
        }
    }
  
    return NULL;
}

void xasplit(std::string& s, const std::string& delim, std::vector<std::string> *ret)
{
    unsigned last = 0;
    unsigned index = s.find_first_of(delim, last);
    while(index != std::string::npos)
    {
        ret->push_back(s.substr(last,index-last));
        last = index+1;
        index = s.find_first_of(delim,last);
    }

    if(index-last > 0)
    {
        ret->push_back(s.substr(last,index-last));
    }
}

static void handleBsConfigRequest(const char* data, ssize_t len, char* input, int *inLen)
{
    U32  tacCycle = 0;
    bool isValid = true;
            
    std::string msg = "";
	vector<std::string> payload;
	std::string delim = XINAN_MESSAGE_BODY_COLON;
	msg.assign(data, len);
    cli_app_log(CLI_LOG_INFO, "msg is %s \n", data)
	xasplit(msg, delim, &payload);
    cli_app_log(CLI_LOG_INFO, "payload len is %s \n", payload[0].c_str());
	if(strcmp(payload[0].c_str(), XINAN_MESSAGE_BODY_TAC_CYCLE) == 0)
	{
		tacCycle = atoi(payload[1].c_str());
		
		if(tacCycle > 0 && tacCycle < 65535)
		   isValid &= true;
		else
		   isValid &= false;
        if(isValid)
        {
            //generate an invalid json message    
            msgConversion(CMD_CONFIG, CFG_UPDATA_TAC_CYCLE, (I8 *)&tacCycle, input, inLen);
        }
        else
        {
            //generate json message    
            msgConversion(CMD_CONFIG, CFG_UPDATA_TAC_CYCLE, (I8 *)&tacCycle, input, inLen);
        }
	}
	else if (strcmp(payload[0].c_str(), XINAN_MESSAGE_BODY_MIN) == 0)
    {
        tacCycle = atoi(payload[1].c_str());
        cli_app_log(CLI_LOG_INFO, "redet min is %d \n", tacCycle);
        if (tacCycle > 0)
            isValid = true;
        else
            isValid = false;
        if (isValid)
        {
             msgConversion(CMD_CONFIG, CFG_DET_INTVL, (I8 *)&tacCycle, input, inLen); 
        }
    }


}

static void handleBsTxTurnOnRequest(const char* data, ssize_t len, char* input, int *inLen)
{
	char    content[2] = {0};
	I32     cellIdx = 0;

	memcpy(content, data, sizeof(U8));
    cellIdx = atoi(content);
	setCellNum = cellIdx;
	if(cellIdx == 0)
	{
	   //open all cell	
	   msgConversion(CMD_CTRL, CT_WIRELISS_ON, NULL, input, inLen);	   
	   cli_app_log(CLI_LOG_NOTICE, "turn on all cell output\n");
	}
	else
	{
	   //open the dedicate cell
	   msgConversion(CMD_CTRL, CT_BBU_PW_ON, (I8 *)&cellIdx, input, inLen);	   
	   cli_app_log(CLI_LOG_NOTICE, "turn on cell %d output\n", cellIdx);	   
	}

}

static void handleBsTxTurnOffRequest(const char* data, ssize_t len, char* input, int *inLen)
{
	char    content[2] = {0};
	I32     cellIdx = 0;

	memcpy(content, data, sizeof(U8));
    cellIdx = atoi(content);
	setCellNum = cellIdx;	
	if(cellIdx == 0)
	{
	   //off all cell	
	   msgConversion(CMD_CTRL, CT_WIRELISS_OFF, NULL, input, inLen);	   
	   cli_app_log(CLI_LOG_NOTICE, "turn off all cell output\n");
	}
	else
	{
	   //off the dedicate cell
	   msgConversion(CMD_CTRL, CT_BBU_PW_OFF, (I8 *)&cellIdx, input, inLen);	   	   
	   cli_app_log(CLI_LOG_NOTICE, "turn off cell %d output\n", cellIdx);	   
	}

}

bool handleLteRfConfigInfo(const char* data, ssize_t len, WirelessConfig * rfConfig)
{
	lteRadioConfig* lte = NULL;
    I32 value = 0;
	
    std::string msg = "";
	vector<std::string> cell;
	vector<std::string> field;
	
	std::string cellDelim = XINAN_MESSAGE_BODY_AT;
	std::string fieldDelim = XINAN_MESSAGE_BODY_COLON;

    rfConfig->capLte.isSupported = 1;
    rfConfig->capLte.enable = 1;
	
	msg.assign(data, len);
    xasplit(msg, cellDelim, &cell);
	for(U32 i = 0; i < cell.size(); i++)
	{
		xasplit(cell[i], fieldDelim, &field);
	
        if(field[0].compare(XINAN_MESSAGE_BODY_IDX))
        {
			cli_app_log(CLI_LOG_INFO, "cell %s configuration\n", field[1].c_str());	
			
	        int cellIdx = atoi(field[1].c_str()) - 1;
            if(cellIdx < 0 && cellIdx > 7)
            {
			    cli_app_log(CLI_LOG_ERROR, "invalid lte cell number %s", field[1].c_str());
				return false;
            }
			
			rfConfig->wirelessSupported[cellIdx] = 1;
			lte = &rfConfig->capLte.lte[cellIdx];
			lte->enable = 1;
			lte->isSaveFs = 1;
        }
    	else if(field[0].compare(XINAN_MESSAGE_BODY_PCI))
    	{
        	value = atoi(field[1].c_str());
        	if(value > 0 && value < 503)
        	{
				lte->pci = value;
        	}
			else
			{
				cli_app_log(CLI_LOG_ERROR, "Invalid PCI %d\n", value);			
				return false;
			}
    	}
    	else if(field[0].compare(XINAN_MESSAGE_BODY_UL_EARFCN))
    	{
        	value = atoi(field[1].c_str());
        	if(value < 65535 || value > 0)
        	{
				lte->ul_earfcn = value;
        	}
			else
			{
				cli_app_log(CLI_LOG_ERROR, "Invalid UL_EARFCN %d\n", value);			
				return false;
			}
    	}
    	else if(field[0].compare(XINAN_MESSAGE_BODY_DL_EARFCN))
    	{
        	value = atoi(field[1].c_str());
        	if(value < 65535 || value > 0)
			{
				lte->dl_earfcn = value;
			}
			else
			{
				cli_app_log(CLI_LOG_ERROR, "Invalid DL_EARFCN %d\n", value);			
				return false;
			}
    	}
    	else if(field[0].compare(XINAN_MESSAGE_BODY_PA))
    	{
    	}
    	else if(field[0].compare(XINAN_MESSAGE_BODY_GA))
    	{
    	}
    	else if(field[0].compare(XINAN_MESSAGE_BODY_SYNC_MODE))
    	{
        	value = atoi(field[1].c_str());
        	if(value < 0 || value > 3)
			{
				lte->syncMode = value;
			}
			else
			{
				cli_app_log(CLI_LOG_ERROR, "Invalid SYNC_MODE %d\n", value);			
				return false;
			}
   		}
    	else if(field[0].compare(XINAN_MESSAGE_BODY_BAND))
    	{
        	value = atoi(field[1].c_str());
        	if(value < 0 || value > 60)
			{
				lte->band = value;
			}
			else
			{
				cli_app_log(CLI_LOG_ERROR, "Invalid BAND %d\n", value);			
				return false;
			}
   		}		
    	else if(field[0].compare(XINAN_MESSAGE_BODY_BAND_WIDTH))
    	{
        	value = atoi(field[1].c_str());
        	if(value == 5 || value == 10 || value == 20 )
			{
				lte->bandWidth = value;
			}
			else
			{
				cli_app_log(CLI_LOG_ERROR, "Invalid BAND_WIDTH %d\n", value);			
				return false;
			}
   		}			
    	else if(field[0].compare(XINAN_MESSAGE_BODY_GPS_DELAY))
    	{
        	value = atoi(field[1].c_str());
        	if(value < -100000 || value > 100000)
			{
				lte->gpsTmDelay = value;
			}
			else
			{
				cli_app_log(CLI_LOG_ERROR, "Invalid GPS_DELAY %d\n", value);			
				return false;
			}
   		}	
    	else if(field[0].compare(XINAN_MESSAGE_BODY_TAC))
    	{
        	value = atoi(field[1].c_str());
        	if(value < 65535 || value > 0)
			{
				lte->tac = value;
			}
			else
			{
				cli_app_log(CLI_LOG_ERROR, "Invalid TAC %d\n", value);			
				return false;
			}
    	}
    	else if(field[0].compare(XINAN_MESSAGE_BODY_PLMN))
    	{
        	value = atoi(field[1].c_str());
        	if(value > 0)
			{
				lte->plmnid = value;
			}
			else
			{
				cli_app_log(CLI_LOG_ERROR, "Invalid PLMN %d\n", value);			
				return false;
			}
    	}		
    	else
    	{
			cli_app_log(CLI_LOG_NOTICE, "message field is not supported\n");
			return false;
    	}
	}

    return true;
}

bool handleGsmRfConfigInfo(const char* data, ssize_t len, WirelessConfig * rfConfig)
{
	gsmRadioConfig* gsm = NULL;
    U32 value = 0;
	
    std::string msg = "";
	vector<std::string> cell;
	vector<std::string> field;
	
	std::string cellDelim = XINAN_MESSAGE_BODY_AT;
	std::string fieldDelim = XINAN_MESSAGE_BODY_COLON;

	rfConfig->capGsm.isSupported = 1;			
	rfConfig->capGsm.enable = 1;
			
	msg.assign(data, len);
	xasplit(msg, cellDelim, &cell);
	for(U32 i =1; i < cell.size(); i++)
	{
        field.clear();
		xasplit(cell[i], fieldDelim, &field);
        cli_app_log(CLI_LOG_DEFAULT, "FILED IS %s  fied is %s cell size %d \n", cell[i].c_str(), field[0].c_str(), cell.size());
		if(field[0].compare(XINAN_MESSAGE_BODY_IDX) == 0)
		{
			
			int cellIdx = atoi(field[1].c_str()) - 1;
            setCellNum = (cellIdx + 1);
			cli_app_log(CLI_LOG_INFO, "cell %s  cell %dconfiguration\n", field[1].c_str(), cellIdx); 
			if(cellIdx < GSM_CELL_START && cellIdx > GSM_CELL_END)
			{
				cli_app_log(CLI_LOG_ERROR, "invalid cell number %s", field[1].c_str());
				return false;
			}
			
			rfConfig->wirelessSupported[cellIdx] = 1;
			if (cellIdx == GSM_CELL_START)
			{
				gsm = &rfConfig->capGsm.gsm[0];
			}

			if (cellIdx == GSM_CELL_END)
			{
				gsm = &rfConfig->capGsm.gsm[1];
			}
			gsm->enable = 1;
		}
		else if(field[0].compare(XINAN_MESSAGE_BODY_BAND) == 0)
		{
			value = atoi(field[1].c_str());
            cli_app_log(CLI_LOG_INFO , "band %d \n", value);
			if(value == 900 || value == 1800)
			{
				gsm->band = value;
			}
			else
			{
				continue;
			}
		}
		else if(field[0].compare(XINAN_MESSAGE_BODY_ARFCN) == 0)
		{
			value = atoi(field[1].c_str());
            cli_app_log(CLI_LOG_INFO , "arfcn %d \n", value);

			if((value > 0 && value < 125) ||
			   (value > 512 && value < 586) ||
			   (value > 637 && value < 736))
			{
				gsm->bcc = value;
			}
			else
			{
				continue;
			}
		}
		else if(field[0].compare(XINAN_MESSAGE_BODY_PLMN) == 0)
		{
            cli_app_log(CLI_LOG_INFO , "plmnd %s \n", field[1].c_str());

            if (field[1].length() == 5 )
            {
			    gsm->mcc = atoi(((field[1].substr(0, 3)).c_str()));
			    gsm->mnc = atoi(((field[1].substr(3, 2)).c_str()));

            }
		}
		else if(field[0].compare(XINAN_MESSAGE_BODY_LAC) == 0)
		{
			value = atoi(field[1].c_str());
            cli_app_log(CLI_LOG_INFO , "lac %d \n", value);

			if(value < 65535 || value > 0)
			{
				gsm->lac = value;
			}
			else
			{
				continue;
			}
		}		
		else if(field[0].compare(XINAN_MESSAGE_BODY_PA) == 0)
		{
			value = atoi(field[1].c_str());
			if(value > 0)
			{
				gsm->lowatt = value;
			}
			else
			{
				continue;
			}
		}
		else if(field[0].compare(XINAN_MESSAGE_BODY_GA) == 0)
		{
			value = atoi(field[1].c_str());
			if(value > 0)
			{
				gsm->upatt = value;
			}
			else
			{
				continue;
			}
		}				
		else
		{
			cli_app_log(CLI_LOG_NOTICE, "message field is not supported\n");
		    continue;			
		}
	}

    return true;
}

bool handleWcdmaRfConfigInfo(const char* data, ssize_t len, WirelessConfig * rfConfig)
{
	wcdmaRadioConfig* wcdma = NULL;
    U32 value = 0;
	
    std::string msg = "";
	vector<std::string> cell;
	vector<std::string> field;
	
	std::string cellDelim = XINAN_MESSAGE_BODY_AT;
	std::string fieldDelim = XINAN_MESSAGE_BODY_COLON;

	rfConfig->capWcdma.isSupported = 1;
	rfConfig->capWcdma.enable = 1;
			
	msg.assign(data, len);
	xasplit(msg, cellDelim, &cell);
	for(U32 i =0; i < cell.size(); i++)
	{
		xasplit(cell[i], fieldDelim, &field);

		if(field[0].compare(XINAN_MESSAGE_BODY_IDX) == 0)
		{
			cli_app_log(CLI_LOG_INFO, "cell %s configuration\n", field[1].c_str()); 
			
			int cellIdx = atoi(field[1].c_str()) - 1;
			if(cellIdx != WCDMA_CELL_START)
			{
				cli_app_log(CLI_LOG_ERROR, "invalid cell number %s", field[1].c_str());
				return false;
			}
			
			rfConfig->wirelessSupported[cellIdx] = 1;
			wcdma = &rfConfig->capWcdma;
		}
		else if(field[0].compare(XINAN_MESSAGE_BODY_PLMN) == 0)
		{ 
			wcdma->mcc = 460;
			wcdma->mnc = 1;
		}
		else if(field[0].compare(XINAN_MESSAGE_BODY_ARFCN) == 0)
		{
			value = atoi(field[1].c_str());
			if(value > 0 && value < 20000)
			{
				wcdma->arfcn = value;
			}
			else
			{
				cli_app_log(CLI_LOG_ERROR, "invalid ARFCN\n");
				return false;
			}
		}
		else if(field[0].compare(XINAN_MESSAGE_BODY_RAC))
		{
			value = atoi(field[1].c_str());
			if(value > 65535 || value < 0)
			{
				wcdma->rac = value;
			}
			else
			{
				cli_app_log(CLI_LOG_ERROR, "invalid RAC\n");
				return false;
			}
		}
		else if(field[0].compare(XINAN_MESSAGE_BODY_LAC))
		{
			value = atoi(field[1].c_str());
			if(value > 65535 || value < 0)
			{
				wcdma->lac = value;
			}
			else
			{
				cli_app_log(CLI_LOG_ERROR, "invalid LAC\n");
				return false;
			}
		}
		else if(field[0].compare(XINAN_MESSAGE_BODY_PSC))
		{
			value = atoi(field[1].c_str());
			if(value > 1000 || value < 0)
			{
				wcdma->psc = value;
			}
			else
			{
				cli_app_log(CLI_LOG_ERROR, "invalid PSC\n");
				return false;
			}
		}		
		else
		{
			cli_app_log(CLI_LOG_NOTICE, "message field is not supported\n");
			return false;			
		}
	}

    return true;
}

static void handleBsRfConfigRequest(const char* data, ssize_t len, char* input, int *inLen)
{
    WirelessConfig wConfig;
	memset(&wConfig, 0x0, sizeof(WirelessConfig));


	char type_str[4] = {'0'};
	int idx;
	sscanf(data,"Type:%[^@]@IDX:%d",type_str, &idx);

	if( ( strncmp("lte", type_str, 3) == 0) && (idx > 0  && idx < 8) )
	{	
		setCellNum = idx;

		wConfig.wirelessSupported[idx - 1] = 1;		
		wConfig.capLte.enable = 1 ;		
		wConfig.capLte.isSupported = 1;	
		wConfig.capLte.lte[idx -1].enable = 1;
		wConfig.capLte.lte[idx -1].isSaveFs = 1;
		cli_app_log(CLI_LOG_NOTICE, "data %s\n", data + 14);

		int pci_num;
		sscanf(data + 14,"@DUPLEX:%[^@]@PCI:%hd@BANDWIDTH:%d@SYNC_MODE:%d@UL_EARFCN:%d@DL_EARFCN:%d@PA:%*d@GPS_DELAY:%d@PLMN:%d@TAC:%d",
			wConfig.capLte.lte[idx -1].desc,
			&pci_num,
			&wConfig.capLte.lte[idx -1].bandWidth,
			&wConfig.capLte.lte[idx -1].syncMode,
			&wConfig.capLte.lte[idx -1].ul_earfcn,
			&wConfig.capLte.lte[idx -1].dl_earfcn,
			&wConfig.capLte.lte[idx -1].gpsTmDelay,
			&wConfig.capLte.lte[idx -1].plmnid,
			&wConfig.capLte.lte[idx -1].tac
		);
		//cli_app_log(CLI_LOG_NOTICE, "DUPLEX %s\n", wConfig.capLte.lte[idx -1].desc);
	//	cli_app_log(CLI_LOG_NOTICE, "PCI %d\n", pci_num);
	//	cli_app_log(CLI_LOG_NOTICE, "bandWidth %d\n", wConfig.capLte.lte[idx -1].bandWidth);

		wConfig.capLte.lte[idx -1].pci = (uint16_t)pci_num;

		bool ret = msgConversion(CMD_CONFIG,CFG_WIRELESS, (I8 *)&wConfig, input, inLen);

    	return;

	}


    std::string msg = "";
	vector<std::string> payload;
	vector<std::string> cell;
	vector<std::string> field;
	
	std::string delim = XINAN_MESSAGE_BODY_HASH;
	std::string cellDelim = XINAN_MESSAGE_BODY_AT;
	std::string fieldDelim = XINAN_MESSAGE_BODY_COLON;
	    	    
	msg.assign(data, len);

	xasplit(msg, delim, &payload);

    //only support gsm
	for (U32 i = 0; i < payload.size(); i++)
	{
	    xasplit(payload[i], cellDelim, &cell);
		xasplit(cell[1], fieldDelim, &field);

        cli_app_log(CLI_LOG_DEFAULT, "cell is %s filed is %s \n", cell[1].c_str(), field[1].c_str());
		if(cell[1].compare(XINAN_MESSAGE_BODY_IDX))
		{
            if(atoi(field[1].c_str()) - 1 >= GSM_CELL_START && atoi(field[1].c_str()) - 1 <= GSM_CELL_END)
            {
	            //gsm                
                cli_app_log(CLI_LOG_INFO, "set gsm config \n");
		        if(!handleGsmRfConfigInfo(payload[i].c_str(), payload[i].length(), &wConfig))
		        {
					cli_app_log(CLI_LOG_ERROR, "something wrong with gsm parameters\n");
					goto invalid;
		        }
            }
            if(atoi(field[1].c_str()) >= LTE_CELL_START && atoi(field[1].c_str()) <= LTE_CELL_END)
            {
	            //gsm 
                cli_app_log(CLI_LOG_INFO, "set lte config \n");

		        if(!handleLteRfConfigInfo(cell[0].c_str(), cell[0].length(), &wConfig))
		        {
					cli_app_log(CLI_LOG_ERROR, "something wrong with lte parameters\n");					
					goto invalid;
		        }
            }
            if(atoi(field[1].c_str()) == WCDMA_CELL_START)
            {
	            //gsm
                 cli_app_log(CLI_LOG_INFO, "set wcdma config \n");

		        if(!handleLteRfConfigInfo(cell[0].c_str(), cell[0].length(), &wConfig))
		        {
					cli_app_log(CLI_LOG_ERROR, "something wrong with wcdma parameters\n");			
					goto invalid;
		        }
            }
		}
        else
        {
			cli_app_log(CLI_LOG_ERROR, "first element should be IDX\n");
            goto invalid;
        }
	}    
	
    msgConversion(CMD_CONFIG,CFG_WIRELESS, (I8 *)&wConfig, input, inLen);
    return;

invalid:
    msgConversion(CMD_CONFIG,CFG_WIRELESS, (I8 *)&wConfig, input, inLen);
    return;
}

static void handleBsRebootRequest(const char* data, ssize_t len, char* input, int *inLen)
{
    msgConversion(CMD_CTRL, CT_RESRART, NULL, input, inLen);
}

static void handleBsQueryConfigRequest(const char* data, ssize_t len, char* input, int *inLen)
{
    msgConversion(CMD_SEARCH, SR_TOTAL_CFG, NULL, input, inLen);
}

static void handleBsTimeConfigRequest(const char* data, ssize_t len, char* input, int *inLen)
{
    const char * pFormat = "%Y-%m-%d %H:%M:%S";
    string time;
    string blank = " ";

    struct tm tmTime;

    time_t utcTime;

    strptime(data, pFormat, &tmTime);
    utcTime = mktime(&tmTime);
    cli_app_log(CLI_LOG_NOTICE, "set system time is data is %s %lu \n", data, utcTime);
    msgConversion(CMD_CTRL,CT_TIME_SYNC, (I8 *)&utcTime, input, inLen);
}

static void handleBsAlarmUeRequest(const char* data, ssize_t len, char* input, int *inLen)
{
	int type = 0;
	BlackList list;
	I8* ptr = &list.imsiList[0];
	memset(&list, 0, sizeof(list));
	
    std::string msg = "";
	vector<std::string> payload;
	vector<std::string> element;
	std::string delim = XINAN_MESSAGE_BODY_HASH;
	
	msg.assign(data, len);
	xasplit(msg, delim, &payload);
	
	type = atoi(payload[0].c_str());

    for(U32 i = 1; i < payload.size(); i++)
    {
        list.number++;
		memcpy(ptr, payload[i].c_str(), payload[i].length());
		ptr += 20;
    }
	
	switch(type)
	{
	    case 1:
			msgConversion(CMD_SEARCH, SR_BLACKLIST, NULL, input, inLen);			
			break;
		case 2:
			msgConversion(CMD_CONFIG, CFG_BLACKLIST_ADD, (I8 *)&list, input, inLen);		
			break;
		case 3:
			msgConversion(CMD_CONFIG, CFG_BLACKLIST_DEL, (I8 *)&list, input, inLen);		
			break;
		default:			
			cli_app_log(CLI_LOG_INFO, "wrong alarm ue type\n", type); 
			break;
	}
}

static void handleBsFtpConfigRequest(const char* data, ssize_t len, char* input, int *inLen)
{
	FTP_INFO    ftpInfo;
    memset(&ftpInfo, 0x0, sizeof(FTP_INFO));
	
    std::string msg = "";
	vector<std::string> payload;
	vector<std::string> element;
	std::string delim = XINAN_MESSAGE_BODY_HASH;
	
	msg.assign(data, len);
	xasplit(msg, delim, &payload);

	memcpy(ftpInfo.ftpserver, payload[0].c_str(), payload[0].length());
	memcpy(ftpInfo.ftpuser, payload[1].c_str(), payload[1].length());
	memcpy(ftpInfo.ftppasswd, payload[2].c_str(), payload[2].length());
	memcpy(ftpInfo.ftpport, payload[3].c_str(), payload[3].length());
	memcpy(ftpInfo.ftptimer, payload[4].c_str(), payload[4].length());
	memcpy(ftpInfo.ftpmaxcount, payload[5].c_str(), payload[5].length());

    msgConversion(CMD_CONFIG, CFG_FTP_INFO, (I8 *)&ftpInfo, input, inLen);
}

static void handleBsFtpQueryRequest(const char* data, ssize_t len, char* input, int *inLen)
{
    msgConversion(CMD_SEARCH, SR_FTP_INFO, NULL, input, inLen);
}

static void handleBsUpgradeRequest(const char* data, ssize_t len, char* input, int *inLen)
{
    std::string msg="";
    msg.assign(data, len);
    vector<std::string> payload;
    stringstream addr;
    std::string delim = XINAN_MESSAGE_BODY_HASH;
    xasplit(msg, delim, &payload);
    if (payload.size() <5)
    {
        msgConversion(CMD_CONFIG, CFG_SOFTWARE_UPDATA, NULL, input, inLen);
        return;
    }
    else
    {
        vector<std::string> cell;
        std::string split = "\\";
        xasplit(payload[0], split, &cell);

        addr << "ftp://" << payload[3] << XINAN_MESSAGE_BODY_COLON 
        << payload[4] << XINAN_MESSAGE_BODY_AT << payload[1] << XINAN_MESSAGE_BODY_COLON
        << payload[2];
        for (int i = 0; i < cell.size(); i++)
        {
            addr << "/" << cell[i];
        }
        cli_app_log(CLI_LOG_NOTICE, "upgrade address is %s \n", addr.str().c_str()); 
    }
    UPGRADE_INFO upgradeInfo;
    memset(&upgradeInfo, 0, sizeof(UPGRADE_INFO));
    memcpy(upgradeInfo.url, addr.str().c_str(), addr.str().length());

    msgConversion(CMD_CONFIG, CFG_SOFTWARE_UPDATA, (I8 *)&upgradeInfo, input, inLen);

    
}
	
static void handleBsQueryLog(const char* data, ssize_t len, char* input, int *inLen)
{
    msgConversion(CMD_SEARCH, SR_LOG_INFO, NULL, input, inLen);
}

static void handleBsDeviceRegisterResponse(const char* data, ssize_t len, char* input, int *inLen)
{
    msgConversion(CMD_OTHERS, SEX_REG_SUCCESS, NULL, input, inLen);
    xinAnServerState = XINAN_SERVER_CONNECTED;    
}
	
static void handleBsSnifferRequest(const char* data, ssize_t len, char* input, int *inLen)
{
    msgConversion(CMD_CTRL, CT_SNIFFER, NULL, input, inLen);
}

static void handleBsHeartBeatReponse(const char* data, ssize_t len, char* input, int *inLen)
{
    msgConversion(CMD_OTHERS, HT_SRV_STATUS_OK, NULL, input, inLen);
}

static void handleBsSnifferConfigRequest(const char* data, ssize_t len, char* input, int *inLen)
{
	WirelessConfig wdata;
    memset(&wdata, 0x0, sizeof(WirelessConfig));
    
	U32 value;
	char *ptr = input;
    int length = 0;
	
    std::string msg = "";
	vector<std::string> payload;
	vector<std::string> cell;
	vector<std::string> field;
	
	std::string delim = XINAN_MESSAGE_BODY_HASH;
	std::string cellDelim = XINAN_MESSAGE_BODY_AT;
	std::string fieldDelim = XINAN_MESSAGE_BODY_COLON;
	    	    
	msg.assign(data, len);
    int id = 0;
	xasplit(msg, delim, &payload);

    //only support gsm
	for (U32 i = 0; i < payload.size(); i++)
	{
	    xasplit(payload[i], cellDelim, &cell);
     
		for(U32 j = 0; j < cell.size(); j++)
		{
			xasplit(cell[j], fieldDelim, &field);
		
	        if(field[0].compare(XINAN_MESSAGE_BODY_IDX) == 0)
	        {
				cli_app_log(CLI_LOG_INFO, "cell %s sniffer configuration\n", field[1].c_str());	
				
		        id = (atoi(field[1].c_str()) - 1);
	            if(id < GSM_CELL_START && id > GSM_CELL_END)
	            {
				    cli_app_log(CLI_LOG_ERROR, "invalid cell number %s", field[1].c_str());
					goto invalid;
	            }
                wdata.wirelessSupported[id] = 1;
				
	        }
            else if(field[0].compare(XINAN_MESSAGE_BODY_AUTOSNIFFER) == 0)
	    	{
	        	value = atoi(field[1].c_str());
	        	if(value == 0 || value == 1 )
	        	{
				    wdata.snfConfig[id].enable = value;
	        	}
				else
				{
					goto invalid;
				}
	    	}
	    	else if(field[0].compare(XINAN_MESSAGE_BODY_CYCLE))
	    	{
	        	value = atoi(field[1].c_str());
	        	if(value > 0)
	        	{	        	    
				    wdata.snfConfig[id].cycle = value;
                }	
				else
				{
					goto invalid;
				}
	    	}
	    	else if(field[0].compare(XINAN_MESSAGE_BODY_CONFIGMODE))
	    	{
	        	value = atoi(field[1].c_str());
	        	if(value > 0 || value < 3)
				{					
				    wdata.snfConfig[id].isAuto = value;
                }	
				else
				{
					goto invalid;
				}
	    	}
	    	else
	    	{
				cli_app_log(CLI_LOG_NOTICE, "message field is not supported\n");
				goto invalid;
	    	}
		}

		if(!msgConversion(CMD_CONFIG, CFG_AIR_SNIFFER, (I8 *)&wdata, ptr, &length))
		{
		    goto invalid;
		}

		ptr += length;
		*inLen += length;
	}
invalid:
	msgConversion(CMD_CONFIG, CFG_AIR_SNIFFER, (I8 *)&wdata, input, inLen);
}

static void handleBsRemoteSshOn(const char* data, ssize_t len, char* input, int *inLen)
{
	REMOTE_SSH remoteSSH;
	memset(&remoteSSH, 0x0, sizeof(REMOTE_SSH));	
	char *ptmp;

	ptmp = strstr((char*)data, "PORT");
	if(ptmp && strchr(ptmp, '@'))
	{
		memcpy(remoteSSH.port, ptmp+5, strchr(ptmp, '@')-ptmp-5);
	}
	ptmp = strstr(ptmp, "USER");
	if(ptmp && strchr(ptmp, '@'))
	{
		memcpy(remoteSSH.user, ptmp+5, strchr(ptmp, '@')-ptmp-5);
	}
	ptmp = strstr(ptmp, "PASSWORD");
	if(ptmp && strchr(ptmp, '@'))
	{
		memcpy(remoteSSH.password, ptmp+9, strchr(ptmp, '@')-ptmp-9);
	}
	ptmp = strstr(ptmp, "SERVERADDR");
	if(ptmp)
	{
		memcpy(remoteSSH.serverAddr, ptmp+11, 15);
	}

	cli_app_log(CLI_LOG_NOTICE, "%s--%s--%s--%s\n", remoteSSH.port, remoteSSH.user, remoteSSH.password, remoteSSH.serverAddr);
	msgConversion(CMD_CTRL, CT_REMOTE_SSH_ON, (I8 *)&remoteSSH, input, inLen);
}

static void handleBsRemoteSshOff(const char* data, ssize_t len, char* input, int *inLen)
{
	msgConversion(CMD_CTRL, CT_REMOTE_SSH_OFF, NULL, input, inLen);
}

static void handleBsVersionSshState(const char* data, ssize_t len, char* input, int *inLen)
{
	msgConversion(CMD_SEARCH, SR_DEV_VERSION, NULL, input, inLen);
}

static bool  ResolveXinanapiMessageHandler(const char* data, ssize_t len, char* input, int *inLen)
{
    unsigned i;
	const char *msgPtr = data;
	ssize_t length = len;
	
    for(i=0; i < sizeof(handlers)/sizeof(HANDLER); i++)
    {
        if(handlers[i].header)
        {
            if(!strncmp(data, handlers[i].header, strlen(handlers[i].header)))
            {
                if(handlers[i].handler)
                {
	                //skip message type
	                msgPtr += XINAN_MESSAGE_TYPE_LENGTH;
	                length -= XINAN_MESSAGE_TYPE_LENGTH;
		            msgPtr += XINAN_MESSAGE_CODE_LENGTH;
	                length -= XINAN_MESSAGE_CODE_LENGTH;
					
                    handlers[i].handler(msgPtr, length, input, inLen);
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
    }

    return false;
}

void processMsgFromXinanServer(const char* buf, ssize_t len, char* input, int *inLen)
{
	cli_app_log(CLI_LOG_DEFAULT, "[server]message: %s\n", buf);
	  	
    const char   *msgPtr = buf;
    ssize_t      length = 0;

    std::string msg = "";
	vector<std::string> payload;
	vector<std::string> element;
	std::string delim = XINAN_MESSAGE_BODY_HASH;
	
	msg.assign(buf, len);
	xasplit(msg, delim, &payload);

    if(payload[0].compare(XINAN_MESSAGE_HEADER_START))
    {
        cli_app_log(CLI_LOG_INFO, "invalid message \n");		
	    return;
    }

	if(payload[1].length() < 2)
	{
        cli_app_log(CLI_LOG_WARNING, "payload is too short\n");		
		
	    return;	   
	}

    //skip msg header and length field
    msgPtr += XINAN_MESSAGE_HEADER_LENGTH;
	length = (len - XINAN_MESSAGE_HEADER_LENGTH);
	cli_app_log(CLI_LOG_DEFAULT, "server msg is %s len is %d\n",msgPtr, length);
    if (ResolveXinanapiMessageHandler(msgPtr, length, input, inLen))
    {
        cli_app_log(CLI_LOG_DEFAULT, "message handling success \n");
    }
    else
    {
        cli_app_log(CLI_LOG_WARNING, "unknown message type \n");		
    }
}

void handleMsgFromXinanServer(const char * inMsgBuf, ssize_t inMsgSize, char* input, ssize_t *inLen)
{
    if( inMsgBuf==NULL )
    {
        return;
    }
    cli_app_log(CLI_LOG_DEFAULT, "recv xinan msg len is %d \n", inMsgSize);
    buffer_dump_log((I8 *)inMsgBuf, inMsgSize, CLI_LOG_DEFAULT);
    recvSmtpMsgBuf.append(inMsgBuf, inMsgSize);

    if( currentSmtpMsgSize==0 )
    {
        if( recvSmtpMsgBuf.length() > XINAN_MESSAGE_HEADER_LENGTH )
        {
            uint16_t len = 0;
            memcpy(&len, recvSmtpMsgBuf.c_str() + 5, 2);
            cli_app_log(CLI_LOG_DEFAULT, "payload len is %d \n ", ntohs(len));
            currentSmtpMsgSize = ntohs(len) + XINAN_MESSAGE_HEADER_LENGTH;
        }
        else
        {
            return;
        }
    }

    while( recvSmtpMsgBuf.length() >= currentSmtpMsgSize )
    {
        std::string tmpBuf;
        tmpBuf.assign(recvSmtpMsgBuf.c_str(), currentSmtpMsgSize);
        recvSmtpMsgBuf.erase(0, currentSmtpMsgSize);
        
        const char* data =tmpBuf.c_str();
        processMsgFromXinanServer(data, currentSmtpMsgSize, input, inLen);

		currentSmtpMsgSize = 0;
        if( recvSmtpMsgBuf.empty() )
        {
            break;
        }

        if( recvSmtpMsgBuf.length() <= XINAN_MESSAGE_HEADER_LENGTH )
        {
            break;
        }

        uint16_t len = 0;
        memcpy(&len, recvSmtpMsgBuf.c_str() + 5, 2);
        currentSmtpMsgSize = ntohs(len) + XINAN_MESSAGE_HEADER_LENGTH; 
    }    
}

static void handleCellConfigMsg(I32 type, I32 code, I32 result, I8 *indata, I8 *outdata, I32* len)
{
	switch(code)
	{
       case CFG_BLACKLIST_ADD:
       case CFG_BLACKLIST_DEL:
	   case CFG_UPDATA_TAC_CYCLE:
       case CFG_DET_INTVL:
	   case CFG_AIR_SNIFFER:
       case CFG_FTP_INFO:
       	   buildBsGeneralResponse(code, result, indata, outdata, len);
		   break;
             
	   case CFG_WIRELESS:
	   case CFG_PA_GAIN:
           buildBsRespnoseWithId(code, result, indata, outdata, len);
           cli_app_log(CLI_LOG_INFO, "response data is %s len is %d \n", outdata + 8, *len);
		   break; 

	   default:
		   cli_app_log(CLI_LOG_ERROR, "handleCellConfigMsg cmdcode %04x not supported\n", code); 		   
		   break;
	}
}

static void handleCellControlMsg(I32 type, I32 code, I32 result, I8 *indata, I8 *outdata, I32* len)
{
	switch(code)
	{
	   case CT_RESRART:
	   case CT_TIME_SYNC:
	   case CT_SNIFFER:
	   case CT_REMOTE_SSH_ON:
	   case CT_REMOTE_SSH_OFF:
	   	   buildBsGeneralResponse(code, result, indata, outdata, len);
           cli_app_log(CLI_LOG_INFO, "response data is %s len is %d \n", outdata + 8, *len);
           break;

       case CT_WIRELISS_ON:
       case CT_WIRELISS_OFF:
       case CT_BBU_PW_OFF:
       case CT_BBU_PW_ON:
           buildBsRespnoseWithId(code, result, indata, outdata, len);
           cli_app_log(CLI_LOG_INFO, "response data is %s len is %d \n", outdata + 8, *len);
		   break;
	   default:
		   cli_app_log(CLI_LOG_ERROR, "handleCellControlMsg cmdcode %04x not supported\n", code); 		   
		   break;
	}
}

static void handleCellSearchMsg(I32 type, I32 code, I32 result, I8 *indata, I8 *outdata, I32* len)
{
    switch(code)
    {
        case SR_TOTAL_CFG:
            buildBsRfConfiguration(code, result, indata, outdata, len);
            cli_app_log(CLI_LOG_INFO, "response data is %s len is %d \n", outdata + 8, *len);
            break;

        case SR_FTP_INFO:
            buildBsFtpInfo(code, indata, outdata, len);
            break;
        case SR_BLACKLIST:
            buildBsQueryAlarmUeResponse(code, result, indata, outdata, len);
            cli_app_log(CLI_LOG_INFO, "response data is %s len is %d \n", outdata + 8, *len);
            break;
		case SR_DEV_VERSION:
			buildBsVersionSshState(code, result, indata, outdata, len);
            cli_app_log(CLI_LOG_INFO, "response data is %s len is %d \n", outdata + 8, *len);
            break;
        default:
            cli_app_log(CLI_LOG_ERROR, "handleCellSearchMsg cmdcode %04x not supported\n", code); 		   
            break;
    }
}

static void handleOtherMsg(I32 type, I32 code, I32 result, I8 *indata, I8 *outdata, I32* len)
{
	RegisterMsg *registeMsg= NULL;
	DevStaus *devStatus = NULL;
	
	switch(code)
	{
	 	case HT_SRV_STATUS_OK:	
			cli_app_log(CLI_LOG_DEFAULT, "no need another heartbeat\n"); 		 
		 	break;
	 	case SEX_REG_SUCCESS:
		 	xinAnServerState = XINAN_SERVER_CONNECTING;
		 	registeMsg=(RegisterMsg *)indata;
	 
			buildBsDeviceRegisterRequest(registeMsg, outdata, len);
            cli_app_log(CLI_LOG_INFO, "register msg is %s , len is %d \n", outdata + 8, *len);
          //  buildBsTimeRequest(outdata + *len, len);
		 	cli_app_log(CLI_LOG_NOTICE, "buildBsDeviceRegisterRequest\n");			
		 	break;

        case DEVICE_REQ_TIMESYNC:
            buildBsTimeRequest(outdata, len);
            cli_app_log(CLI_LOG_INFO, "request time sync msg is %s , len is %d \n", outdata + 8, *len);
            break;

	 	case DEVICE_STATUS:
		 	devStatus = (DevStaus *)indata;
			
            buildBsDeviceStatusReport(devStatus, outdata, len);
		 	cli_app_log(CLI_LOG_NOTICE, "buildBsDeviceStatusRepor msg %s , len %d\n", outdata + 8, *len);
		 	break;
		case SNF_RESULT:
			buildBsSnifferResult(SNF_RESULT, indata, outdata, len);
		 	cli_app_log(CLI_LOG_NOTICE, "buildBsSnifferResult\n");
			break;
        case BLACKLIST_ALERT:
            buildBsAlarmUeReport(code, result, indata, outdata, len);
            break;     
		default:
			cli_app_log(CLI_LOG_NOTICE, "unsupported command code failed\n");			
			break;
     }

}

void sendMsgToXinAnServer(const char* buf, ssize_t len, char* output, int * outlen)
{
	cli_app_log(CLI_LOG_DEFAULT, "Sending Json message: %s\n", buf);
		
	//todo, decoder json string
	I32 cmdType;
	I32 cmdCode;
    I32 result;
	I8	outdata[65535];
	
	if(rspMsgConversion(&cmdType, &cmdCode, &result, (I8 *)buf, outdata, len))
	{
		switch(cmdType)
		{
			case CMD_OTHERS:
				handleOtherMsg(cmdType, cmdCode, result, outdata, output, outlen);
				break;
			case CMD_CONFIG:
				handleCellConfigMsg(cmdType, cmdCode, result, outdata, output, outlen);
				break;
			case CMD_CTRL:
				handleCellControlMsg(cmdType, cmdCode, result, outdata, output, outlen);				
				break;
			case CMD_SEARCH:
				handleCellSearchMsg(cmdType, cmdCode, result, outdata, output, outlen);
				break;
			default:
				cli_app_log(CLI_LOG_ERROR, "not support command type: %s\n", cmdType);
				break;
		}
	}
}

static int buildBsMsgHeader(I8 *outdata, I32 paraLen)
{
//	stringstream hdrMsg;

//	hdrMsg << XINAN_MESSAGE_HEADER_START << XINAN_MESSAGE_BODY_HASH;
//	hdrMsg << hex << setfill('0') << setw(4) << paraLen;
//    hdrMsg << XINAN_MESSAGE_BODY_HASH;

//	memcpy(outdata, hdrMsg.str().c_str(),hdrMsg.str().length());
    I32 len = 0;
    uint16_t ParaLen = htons(static_cast<uint16_t>(paraLen));
    len += sprintf(outdata, "%s%s", XINAN_MESSAGE_HEADER_START, XINAN_MESSAGE_BODY_HASH);
    memcpy(outdata + len, &ParaLen, 2);
    len += 2;
    len += sprintf(outdata + len, "%s", XINAN_MESSAGE_BODY_HASH);
	return len;
}

static void buildBsGeneralResponse(I32 code, I32 result, I8 *indata, I8 *outdata, I32* len)
{
	int length = 0;
	
   	stringstream msgStream;
   	msgStream << XINAN_MESSAGE_TYPE_BS_CONFIG;
    msgStream << matchStringValue(cmdResponse, code);
    if (result != RST_FAILED)
    {
	    msgStream << 0;
    }
    else
    {
        msgStream << 1;
    }

	length = buildBsMsgHeader(outdata, msgStream.str().length());

	memcpy(outdata + length, msgStream.str().c_str(), msgStream.str().length());
	*len = length + msgStream.str().length();
    outdata[*len] = '\0';
}

static void buildBsRespnoseWithId(I32 code, I32 result, I8 *indata, I8 *outdata, I32* len)
{
	int length = 0;
	
   	stringstream msgStream;
   	msgStream << XINAN_MESSAGE_TYPE_BS_CONFIG;
    msgStream << matchStringValue(cmdResponse, code);
    if (result != RST_FAILED)
    {
	    msgStream << 0;
    }
    else
    {
        msgStream << 1;
    }
    msgStream << XINAN_MESSAGE_BODY_HASH << setCellNum;
	length = buildBsMsgHeader(outdata, msgStream.str().length());

	memcpy(outdata + length, msgStream.str().c_str(), msgStream.str().length());
	*len = length + msgStream.str().length();
    outdata[*len] = '\0';
}


static void buildBsTimeRequest(char* output, int* outlen)
{
	int length = 0;
   	stringstream msgStream;
   	msgStream << XINAN_MESSAGE_TYPE_BS_CONFIG;
    msgStream << XINAN_MESSAGE_CODE_TIME_REQUEST;
	
	length = buildBsMsgHeader(output, msgStream.str().length());

	memcpy(output + length, msgStream.str().c_str(), msgStream.str().length());
	
	*outlen = length + msgStream.str().length();
    output[*outlen] = '\0';
}

static void buildBsDeviceRegisterRequest(RegisterMsg *reginfo, char* output, int* outlen)
{
	int length = 0;
   	stringstream msgStream;
	
   	msgStream << XINAN_MESSAGE_TYPE_BS_CONFIG;
    msgStream << XINAN_MESSAGE_CODE_DEVICE_REGISTER_REQUEST;

    //msgStream << XINAN_MESSAGE_BODY_IDX << XINAN_MESSAGE_BODY_COLON << 0;
	//msgStream << XINAN_MESSAGE_BODY_AT;
	//msgStream << XINAN_MESSAGE_BODY_STATE;
	msgStream << XINAN_MESSAGE_BODY_IP << queryWanIpAddress() << XINAN_MESSAGE_BODY_AT;
    msgStream << "ID" << XINAN_MESSAGE_BODY_COLON << dev_conf.ftp.ftpbsic << XINAN_MESSAGE_BODY_AT;
    msgStream << "TAG" << XINAN_MESSAGE_BODY_COLON << dev_conf.ftp.ftpcompany;

	length = buildBsMsgHeader(output, msgStream.str().length());
	
	memcpy(output + length, msgStream.str().c_str(), msgStream.str().length());
	*outlen = length + msgStream.str().length();
    output[*outlen] = '\0';
}

typedef struct {
	int id;
	int state;
}BsDeviceStats;

typedef struct {
	BsDeviceStats states[7];
	int len;
}BsDeviceStatsType;

static void buildBsDeviceStatusReport(DevStaus *status, char* output, int* outlen)
{
   	stringstream msgStream;
	int length = 0;
	
	BsDeviceStatsType  statsType;
	memset(&statsType, 0, sizeof(statsType));

   	msgStream << XINAN_MESSAGE_TYPE_BS_CONFIG;
    msgStream << XINAN_MESSAGE_CODE_STATUS_REPORT;
    bool gsmType = false;

	for(int i = 0; i < CELL_NUM; i++)
	{
        if (status->bbu[i].active != -1)
        {
            if (i >= GSM_CELL_START && i <= GSM_CELL_END && !gsmType)
            {
                msgStream << XINAN_MESSAGE_BODY_TYPE << XINAN_MESSAGE_BODY_COLON << XINAN_MESSAGE_BODY_GSM << XINAN_MESSAGE_BODY_HASH;
                gsmType = true;
            }
			else if (i >= LTE_CELL_START && i <= LTE_CELL_END )
			{
				//msgStream << XINAN_MESSAGE_BODY_TYPE << XINAN_MESSAGE_BODY_COLON << XINAN_MESSAGE_BODY_LTE << XINAN_MESSAGE_BODY_HASH;
				// lteType = true;
				statsType.states[statsType.len].id = (i + 1);
				statsType.states[statsType.len].state = status->bbu[i].active;
				statsType.len++;
				continue;
			}    

	        msgStream << XINAN_MESSAGE_BODY_IDX << XINAN_MESSAGE_BODY_COLON << (i + 1);
	    	msgStream << XINAN_MESSAGE_BODY_AT;
	    	msgStream << XINAN_MESSAGE_BODY_STATE;
		    msgStream << status->bbu[i].active;           
		    if (i == CELL_NUM - 1) continue;    
                msgStream << XINAN_MESSAGE_BODY_HASH;
        }
	    
	}
	
	msgStream << XINAN_MESSAGE_BODY_IP << queryWanIpAddress() << XINAN_MESSAGE_BODY_AT;
    msgStream << "ID" << XINAN_MESSAGE_BODY_COLON << dev_conf.ftp.ftpbsic << XINAN_MESSAGE_BODY_AT;
    msgStream << "TAG" << XINAN_MESSAGE_BODY_COLON << dev_conf.ftp.ftpcompany;


	msgStream << XINAN_MESSAGE_BODY_HASH << XINAN_MESSAGE_BODY_TYPE << XINAN_MESSAGE_BODY_COLON << XINAN_MESSAGE_BODY_LTE;
	for(int i = 0; i < statsType.len; ++i)
	{
		msgStream << XINAN_MESSAGE_BODY_HASH << XINAN_MESSAGE_BODY_IDX << XINAN_MESSAGE_BODY_COLON << statsType.states[i].id;
		msgStream << XINAN_MESSAGE_BODY_AT << XINAN_MESSAGE_BODY_STATE << statsType.states[i].state;
	}
	length = buildBsMsgHeader(output, msgStream.str().length());
	
	memcpy(output + length, msgStream.str().c_str(), msgStream.str().length());
	*outlen = length + msgStream.str().length();
    output[*outlen] = '\0';
}

static void buildBsFtpInfo(I32 code, I8 *indata, I8 *outdata, I32* len)
{
	FTP_INFO*    ftpInfo = (FTP_INFO *)indata;

   	stringstream msgStream;
	int length = 0;
	
	msgStream << XINAN_MESSAGE_TYPE_BS_CONFIG;
	msgStream << matchStringValue(cmdResponse, code);

	msgStream << ftpInfo->ftpserver << XINAN_MESSAGE_BODY_HASH;
	msgStream << ftpInfo->ftpuser << XINAN_MESSAGE_BODY_HASH;
	msgStream << ftpInfo->ftppasswd << XINAN_MESSAGE_BODY_HASH;
	msgStream << ftpInfo->ftpport << XINAN_MESSAGE_BODY_HASH;
	msgStream << ftpInfo->ftptimer << XINAN_MESSAGE_BODY_HASH;
	msgStream << ftpInfo->ftpmaxcount;
	
	length = buildBsMsgHeader(outdata, msgStream.str().length());
	
	memcpy(outdata + length, msgStream.str().c_str(), msgStream.str().length());
	*len = length + msgStream.str().length();
}
	
static void buildBsSnifferResult(I32 code, I8 *indata, I8 *outdata, I32* len)
{
	gsmSnifferResult *info = (gsmSnifferResult *)indata;
	stringstream msgStream;
	int length = 0;
	
	msgStream << XINAN_MESSAGE_TYPE_BS_CONFIG;
	msgStream << XINAN_MESSAGE_CODE_DEVICE_SNIFFER_RESULT;
    cli_app_log(CLI_LOG_INFO, "sniffer result num is %d \n", info->cellNum);
    for(U32 i = 0; i < info->cellNum; i++)
    {
        msgStream << XINAN_MESSAGE_BODY_PLMN << XINAN_MESSAGE_BODY_COLON << info->cell[i].wPlmnid << XINAN_MESSAGE_BODY_AT;
        msgStream << XINAN_MESSAGE_BODY_ARFCN << XINAN_MESSAGE_BODY_COLON << info->cell[i].wARFCN << XINAN_MESSAGE_BODY_AT;
        msgStream << XINAN_MESSAGE_BODY_BSIC << XINAN_MESSAGE_BODY_COLON << info->cell[i].wBSIC << XINAN_MESSAGE_BODY_AT;
        msgStream << XINAN_MESSAGE_BODY_LAC << XINAN_MESSAGE_BODY_COLON << info->cell[i].wLAC << XINAN_MESSAGE_BODY_AT;
        msgStream << XINAN_MESSAGE_BODY_C1 << XINAN_MESSAGE_BODY_COLON << info->cell[i].cC1 << XINAN_MESSAGE_BODY_AT;
        msgStream << XINAN_MESSAGE_BODY_C2 << XINAN_MESSAGE_BODY_COLON << info->cell[i].bC2 << XINAN_MESSAGE_BODY_AT;		
        msgStream << XINAN_MESSAGE_BODY_RSSI << XINAN_MESSAGE_BODY_COLON << info->cell[i].cRSSI;

		if(i == info->cellNum - 1) continue;

		msgStream << XINAN_MESSAGE_BODY_HASH;
    }

	length = buildBsMsgHeader(outdata, msgStream.str().length());

	memcpy(outdata + length, msgStream.str().c_str(), msgStream.str().length());
	*len = length + msgStream.str().length();	
    outdata[*len] = '\0';
}

static void buildBsAlarmUeReport(I32 code, I32 result, I8 *indata, I8 *outdata, I32* len)
{
   	stringstream msgStream;
	int length = 0;

   	msgStream << XINAN_MESSAGE_TYPE_BS_CONFIG;
    msgStream << XINAN_MESSAGE_CODE_ALARMUE_REPORT;
	msgStream << indata;
	msgStream << XINAN_MESSAGE_BODY_HASH;
	msgStream << dev_conf.ftp.ftpbsic;

	length = buildBsMsgHeader(outdata, msgStream.str().length());

	memcpy(outdata + length, msgStream.str().c_str(), msgStream.str().length());
	*len = length + msgStream.str().length();
}

static void buildBsQueryAlarmUeResponse(I32 code, I32 result, I8 *indata, I8 *outdata, I32* len)
{
	
   	stringstream msgStream;
	int length = 0;

   	msgStream << XINAN_MESSAGE_TYPE_BS_CONFIG;
    msgStream << XINAN_MESSAGE_CODE_ALARMUE_CONFIG_RESPONSE;
    msgStream << (indata + 1);	
	cli_app_log(CLI_LOG_INFO, "list is %s \n", indata);

	length = buildBsMsgHeader(outdata, msgStream.str().length());

	memcpy(outdata + length, msgStream.str().c_str(), msgStream.str().length());
	*len = length + msgStream.str().length();		
    outdata[*len] = '\0';
}

static int buildLteRfConfig(WirelessConfig *info, I8 *outdata, U8 cellIdx)
{
	WirelessConfig *rfPtr = info;
	
   	stringstream msgStream;
	msgStream << XINAN_MESSAGE_BODY_HASH;
	msgStream << XINAN_MESSAGE_BODY_IDX << XINAN_MESSAGE_BODY_COLON << cellIdx + 1 << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_DUPLEX << XINAN_MESSAGE_BODY_COLON << dev_conf.capLte.lte[cellIdx].desc << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_PCI << XINAN_MESSAGE_BODY_COLON << rfPtr->capLte.lte[cellIdx].pci << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_UL_EARFCN << XINAN_MESSAGE_BODY_COLON << rfPtr->capLte.lte[cellIdx].ul_earfcn << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_DL_EARFCN << XINAN_MESSAGE_BODY_COLON << rfPtr->capLte.lte[cellIdx].dl_earfcn << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_PA << XINAN_MESSAGE_BODY_COLON << dev_conf.pa[cellIdx].gain << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_PLMN << XINAN_MESSAGE_BODY_COLON << rfPtr->capLte.lte[cellIdx].plmnid << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_BAND_WIDTH << XINAN_MESSAGE_BODY_COLON << rfPtr->capLte.lte[cellIdx].bandWidth << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_BAND << XINAN_MESSAGE_BODY_COLON << rfPtr->capLte.lte[cellIdx].band << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_SYNC_MODE << XINAN_MESSAGE_BODY_COLON << rfPtr->capLte.lte[cellIdx].syncMode << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_GPS_DELAY << XINAN_MESSAGE_BODY_COLON << rfPtr->capLte.lte[cellIdx].gpsTmDelay << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_TAC << XINAN_MESSAGE_BODY_COLON << dev_conf.capLte.lte[cellIdx].tac;

	memcpy(outdata, msgStream.str().c_str(),msgStream.str().length());
	outdata[msgStream.str().length()] = '\0';
	return msgStream.str().length();
}

static int buildGsmRfConfig(WirelessConfig *info, I8 *outdata, U8 cellIdx)
{
	gsmRadioConfig *gsm = &info->capGsm.gsm[cellIdx - GSM_CELL_START];
	
   	stringstream msgStream;
	msgStream << XINAN_MESSAGE_BODY_HASH;
	msgStream << XINAN_MESSAGE_BODY_IDX << XINAN_MESSAGE_BODY_COLON << cellIdx + 1 << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_BAND << XINAN_MESSAGE_BODY_COLON <<  gsm->band << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_ARFCN << XINAN_MESSAGE_BODY_COLON << gsm->bcc << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_PLMN << XINAN_MESSAGE_BODY_COLON << setw(3) << gsm->mcc << setfill('0') << setw(2) << gsm->mnc << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_LAC << XINAN_MESSAGE_BODY_COLON << gsm->lac << XINAN_MESSAGE_BODY_AT;
    msgStream << XINAN_MESSAGE_BODY_PA << XINAN_MESSAGE_BODY_COLON << gsm->lowatt << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_GA << XINAN_MESSAGE_BODY_COLON << gsm->upatt ;
    

	memcpy(outdata, msgStream.str().c_str(),msgStream.str().length());
	outdata[msgStream.str().length()] = '\0';
	return msgStream.str().length();
}

static int buildWcdmaRfConfig(WirelessConfig *info, I8 *outdata, U8 cellIdx)
{
	wcdmaRadioConfig *rfPtr = &info->capWcdma;
	
   	stringstream msgStream;

	msgStream << XINAN_MESSAGE_BODY_TYPE << XINAN_MESSAGE_BODY_COLON << XINAN_MESSAGE_BODY_LTE << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_IDX << XINAN_MESSAGE_BODY_COLON << cellIdx + 1 << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_PLMN << XINAN_MESSAGE_BODY_COLON << setw(3) << rfPtr->mcc << setfill('0') << setw(2) << rfPtr->mnc << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_LAC << XINAN_MESSAGE_BODY_COLON << rfPtr->lac << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_ARFCN << XINAN_MESSAGE_BODY_COLON << rfPtr->arfcn << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_PSC << XINAN_MESSAGE_BODY_COLON << rfPtr->psc << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_RAC << XINAN_MESSAGE_BODY_COLON << rfPtr->rac << XINAN_MESSAGE_BODY_AT;
	msgStream << XINAN_MESSAGE_BODY_CELLID << XINAN_MESSAGE_BODY_COLON << rfPtr->cellId<< XINAN_MESSAGE_BODY_AT;	
	msgStream << XINAN_MESSAGE_BODY_HASH;

	memcpy(outdata, msgStream.str().c_str(),msgStream.str().length());
	return msgStream.str().length();
}

static void buildBsRfConfiguration(I32 code, I32 result, I8 *indata, I8 *outdata, I32* len)
{
     WirelessConfig wconfig;
	 memset(&wconfig, 0, sizeof(wconfig));
	 conversionConfig(&wconfig);
     WirelessConfig* info = &wconfig;
	 stringstream msgStream;
	 int length = 0;
	 int totalLen = 0;

	 I8 *msgPtr = indata;
	 msgStream << XINAN_MESSAGE_TYPE_BS_CONFIG ;
	 msgStream << matchStringValue(cmdResponse, code);
     bool haveSetLte= false;
     bool haveSetGsm = false;
 
     

	 for(int i = CELL_NUM - 1; i >= 0; i--)
	 {
	     if(info->wirelessSupported[i] && (i >= LTE_CELL_START && i <= LTE_CELL_END))
	     {
             if (!haveSetLte)
             {
				msgStream << XINAN_MESSAGE_BODY_HASH << XINAN_MESSAGE_BODY_TYPE << XINAN_MESSAGE_BODY_COLON << XINAN_MESSAGE_BODY_LTE << XINAN_MESSAGE_BODY_AT;
                msgStream << XINAN_MESSAGE_BODY_TAC_CYCLE << XINAN_MESSAGE_BODY_COLON << dev_conf.capLte.tac_cycle;
                haveSetLte = true;
             }
			
	        buildLteRfConfig(info, msgPtr, i);
			 //msgPtr += length;
			// totalLen += length;
			msgStream << msgPtr;
	     }
        else if(info->wirelessSupported[i] && (i >= GSM_CELL_START && i <= GSM_CELL_END))	     
		 {
             if (!haveSetGsm)
             {
                msgStream << XINAN_MESSAGE_BODY_TYPE << XINAN_MESSAGE_BODY_COLON << XINAN_MESSAGE_BODY_GSM << XINAN_MESSAGE_BODY_AT
                << XINAN_MESSAGE_BODY_MIN << XINAN_MESSAGE_BODY_COLON << info->capGsm.intvl ;
                haveSetGsm = true;
             }
	         buildGsmRfConfig(info, msgPtr, i);
			//  msgPtr += length;
			//  totalLen += length;	
			msgStream << msgPtr;		 
	     }		 
		else if(info->wirelessSupported[i] && (i == WCDMA_CELL_START))
		 {
	         length = buildWcdmaRfConfig(info, msgPtr, i);
			 msgPtr += length;
			 totalLen += length;	     
	     }
	 }
     //indata[totalLen] = '\0';

//	cli_app_log(CLI_LOG_NOTICE, "indata = %s\n", indata);

	// msgStream << indata;

	 length = buildBsMsgHeader(outdata, msgStream.str().length());
	 
	 memcpy(outdata + length, msgStream.str().c_str(), msgStream.str().length());
	 *len = length + msgStream.str().length(); 
     outdata[*len] = '\0';
}

static void buildBsVersionSshState(I32 code, I32 result, I8 *indata, I8 *outdata, I32* len)
{
	stringstream msgStream;
	int length = 0;
	I8 version[10] = {0};
	char *ptmp;
	
	msgStream << XINAN_MESSAGE_TYPE_BS_CONFIG;
	msgStream << matchStringValue(cmdResponse, code);

	ptmp = strstr(indata, "currentSoftVer");
	if(ptmp && strstr(ptmp, "originalSoftVer"))
	{
		memcpy(version, ptmp+18, strstr(ptmp, "originalSoftVer")-ptmp-18-4);

	}
	if(result != RST_FAILED)
	{
		msgStream << 0 << XINAN_MESSAGE_BODY_HASH << "version:" << version;
		msgStream << XINAN_MESSAGE_BODY_AT << "sshState:" << ssh_state;
	}
	else
	{
		msgStream << 1;
	}
	length = buildBsMsgHeader(outdata, msgStream.str().length());
	
	memcpy(outdata + length, msgStream.str().c_str(), msgStream.str().length());
	*len = length + msgStream.str().length();	
}


